package paskal.abstractplayer;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import paskal.audio.player.CashedPlayer;
import paskal.audio.player.Controller;
import paskal.audio.player.PlayerException;
import paskal.audio.player.PlayerListener;

public class AbstractPlayer {

	private CashedPlayer player = null;
	private PlaylistListener listener;
	private Controller controller = null;
	private Playlist playlist = null;
	private Map<String, Object> audioInfo = null;

	public AbstractPlayer(PlayerListener listener) {
		player = new CashedPlayer();
		player.addPlayerListener(listener);
		controller = player;
	}

	public void addPlaylistListener(PlaylistListener listener) {
		this.listener = listener;
	}

	public boolean isRunning() {
		return (player.getStatus() == CashedPlayer.PLAYING);
	}

	public void setVolume(float volume) {
		try {
			controller.setVolume(volume);
		} catch (PlayerException e) {
			e.printStackTrace();
		}
	}

	public void setPercentagePosition(double p) {
		try {
			controller.setPercentagePosition(p);
		} catch (PlayerException e) {
			e.printStackTrace();
		}
	}

	public int getDuration() {
		if (playlist.get().getDuration() != 0) {
			return playlist.get().getDuration();
		}
		long milliseconds = -1;
		int byteslength = -1;
		if (audioInfo != null) {
			if (audioInfo.containsKey("audio.length.bytes")) {
				byteslength = ((Integer) audioInfo.get("audio.length.bytes"))
						.intValue();
			}
			if (audioInfo.containsKey("duration")) {
				milliseconds = (int) (((Long) audioInfo.get("duration"))
						.longValue()) / 1000000;
			} else {
				// Try to compute duration
				float samplerate = -1.0f;
				int framesize = -1;

				if (audioInfo.containsKey("audio.samplerate.hz")) {
					samplerate = ((Float) audioInfo.get("audio.samplerate.hz"))
							.floatValue();
				}
				if (audioInfo.containsKey("audio.framesize.bytes")) {
					framesize = ((Integer) audioInfo
							.get("audio.framesize.bytes")).intValue();
				}
				milliseconds = (long) (byteslength / framesize / samplerate);
			}
		}
		return (int) milliseconds;
	}

	public void pause() {
		try {
			controller.pause();
		} catch (PlayerException e) {
			e.printStackTrace();
		}
	}

	public void resume() {
		try {
			controller.resume();
		} catch (PlayerException e) {
			e.printStackTrace();
		}
	}

	public void play() {
		if (player.getStatus() == CashedPlayer.PAUSED) {
			try {
				controller.resume();
			} catch (PlayerException e) {
				e.printStackTrace();
			}
		} else if (player.getStatus() == CashedPlayer.OPENED) {
			try {
				controller.play();
			} catch (PlayerException e) {
				e.printStackTrace();
			}
		} else if ((player.getStatus() == CashedPlayer.UNKNOWN)
				|| (player.getStatus() == CashedPlayer.STOPPED)) {
			try {
				if (playlist.get().getFilePath() != null) {
					controller.open(new File(playlist.get().getFilePath()));
				} else {
					controller.open(new URL(playlist.get().getUrl()));
				}
				controller.play();
			} catch (MalformedURLException | PlayerException e) {
				e.printStackTrace();
			}
		}
	}

	public void stop() {
		try {
			controller.stop();
		} catch (PlayerException e) {
			e.printStackTrace();
		}
	}

	public void previous() {
		playlist.previous();
		boolean flag = (player.getStatus() == CashedPlayer.PLAYING) ? true
				: false;
		try {
			if (playlist.get().getFilePath() != null) {
				controller.open(new File(playlist.get().getFilePath()));
			} else {
				controller.open(new URL(playlist.get().getUrl()));
			}
		} catch (MalformedURLException | PlayerException e) {
			e.printStackTrace();
		}
		if (flag) {
			try {
				player.play();
			} catch (PlayerException e) {
				e.printStackTrace();
			}
		}
	}

	public void next() {
		playlist.next();
		boolean flag = (player.getStatus() == CashedPlayer.PLAYING) ? true
				: false;
		try {
			if (playlist.get().getFilePath() != null) {
				controller.open(new File(playlist.get().getFilePath()));
			} else {
				controller.open(new URL(playlist.get().getUrl()));
			}
		} catch (MalformedURLException | PlayerException e) {
			e.printStackTrace();
		}
		if (flag) {
			try {
				player.play();
			} catch (PlayerException e) {
				e.printStackTrace();
			}
		}
	}

	public void play(int index) {
		playlist.get(index);
		try {
			if (playlist.get().getFilePath() != null) {
				controller.open(new File(playlist.get().getFilePath()));
			} else {
				controller.open(new URL(playlist.get().getUrl()));
			}
		} catch (MalformedURLException | PlayerException e) {
			e.printStackTrace();
		}
		try {
			player.play();
		} catch (PlayerException e) {
			e.printStackTrace();
		}
	}

	public Playlist getPlaylist() {
		return playlist;
	}

	public void setPlaylist(Playlist playlist) {
		this.playlist = playlist;
		if (listener != null)
			listener.onPlayListUpdated();
	}

	public String getTitle() {
		return playlist.get().toString();
	}

	public Map<String, Object> getAudioInfo() {
		return audioInfo;
	}

	public void setAudioInfo(Map<String, Object> audioInfo) {
		this.audioInfo = audioInfo;
	}

	public void close() {
		player.clearCash();
	}

	public File getFile() {
		return player.getSource();
	}
}